<?php
/**
 * Copyright (c) 2018,2345
 * 摘    要：MySQL 类程序
 * 作    者：林幸亿
 * 修改日期：2018.04.20
 */

/*
 * 参考网址
 * https://www.startutorial.com/articles/view/php-crud-tutorial-part-1/
 * https://www.oschina.net/code/snippet_169278_47749
 * https://phpenthusiast.com/blog/the-singleton-design-pattern-in-php
 * https://www.phpro.org/tutorials/Pagination-with-PHP-and-PDO.html
 */

class MysqlDb
{
    // Hold the class instance.
    private static $instance = null;
    private $conn;
    
    //数据库的建立
    private $dbName = 'addressbook';
    private $dbHost = 'localhost';
    private $dbUsername = 'root';
    private $dbUserPassword = '';

    /**
     * 功    能：The db connection is established in the private constructor.
     * 修改日期：2018-4-18
     */
    private function __construct()
    {
        try
        {
            $this->conn = new PDO(
                                "mysql:host={$this->dbHost};
                                dbname={$this->dbName}",
                                $this->dbUsername, 
                                $this->dbUserPassword
                            );
        }
        catch (Exception $e)
        {
            //die($e->getMessage());
            die("Couldn't connect to database.");
        }
    }
   
    /**
     * 功    能：Like the constructor, we make __clone private so nobody can clone the instance
     * 修改日期：2018-4-25
     */
    private function __clone(){
    }

    /**
     * 修改   日期：2018-4-23
     */
    function __destruct() {
        $this->disconnect();
        //echo "MySQL Object Destroyed \n";
    }
    
    /**
     * 修改日期：2018-4-18
     */
    public static function getInstance()
    {
        if(! self::$instance)
        {
            self::$instance = new MysqlDb();
        }

        return self::$instance;
    }

    /**
     * 修改日期：2018-4-18
     * @return object
     */
    public function getConnection()
    {
        return $this->conn;
    }
    
    /**
     * 修改   日期：2018-4-23
     * 参考网址URL：https://stackoverflow.com/questions/18277233/pdo-closing-connection
     */
    public function disconnect()
    {
	$this->conn = null;
    }

    /**
     * 功    能：用于选择一组数据。 Select a single record and return else return false if unsuccessful
     * 修改日期：2018-4-18
     *
     * @param string $sql 
     * @param array $array
     * @return object
     */
    public function find($sql, $array = array())
    {
        $ok = $this->process($sql, $array);
        if ($ok)
        {
            $this->results->setFetchMode(PDO::FETCH_ASSOC);
            $data = $this->results->fetch();
            return $data;
        }
        else
        {
            return false;
        }
    }

    /**
     * 功    能：用于选择多组数据。 Select and retrieve multiple records else return empty array if unsuccessful
     * 修改日期：2018-4-18
     *
     * @param string $sql 
     * @param array $array
     * @return object
     */
    public function finds($sql, $array = array())
    {
        $ok = $this->process($sql, $array);

        if ($ok)
        {
            $this->results->setFetchMode(PDO::FETCH_ASSOC);
            $data = $this->results->fetchAll();
            return $data;
        }
        else
        { 
            return array();
        }
    }

    /**
     * 功    能：修改数据。 Update one or multiple records and return the number of rows affected else 0 for none and -1 if unsuccessful
     * 修改日期：2018-4-18
     *
     * @param string $sql 
     * @param array $array
     * @return object
     */
    public function update($sql, $array = array())
    {
        $ok = $this->process($sql, $array);
        if ($ok === false)
        {
            return -1; //执行出错返回-1
        }
        else if ($ok)
        {
            return $this->results->rowCount();
        }
        else
        {
            return 0;
        }
    }

    /**
     * 功    能：Insert one record and return insert ID if successful, else return false.
     * 修改日期：2018-4-18
     *
     * @param string $sql 
     * @param array $array
     * @return object
     */
    public function insert($sql, $array = array())        
    {
        $ok = $this->process($sql, $array);
        if ($ok)
        {
            $id = $this->cont->lastInsertId();
            $id = $id ? $id : 1;
            return $id;
        }
        else
        {
            return false;
        }
    }

    /**
     * 功    能：Delete one or multiple records.
     * 修改日期：2018-4-18
     *
     * @param string $sql 
     * @param array $array
     * @return object
     */
    public function delete($sql, $array = array())
    {
        $ok = $this->process($sql, $array);
        if ($ok === false)
        {
            return -1; //执行出错返回-1
        }
        else if ($ok)
        {
            return $this->results->rowCount();
        }
        else
        {
            return 0;
        }
    }

    /**
     * 功    能：Can be used for complicated queries.
     * 修改日期：2018-4-18
     *
     * @param string $sql 
     * @param array $array
     * @return object
     */
    public function query($sql, $array = array())
    {
        return $this->process($sql, $array);
    }
    
    /**
     * 功    能：Used by other functions such as insert, update and delete to check for database connection and convert into prepared statement.
     * 修改日期：2018-4-18
     *
     * @param string $sql 
     * @param array $array
     * @return object
     */
    private function process($sql, $array)
    {
        if (is_null($this->conn))
        {        
            $this->conn = $this->getConnection();
        }

        $this->results = $this->conn->prepare($sql);
        //die(var_dump(print_r($this->results->errorInfo())));
        //print_r($this->results->errorInfo());
        return $this->results->execute($array);
    }

}
